package com.hp.snap.gr.action.impl;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hp.snap.gr.exception.ActionException;
import com.hp.snap.gr.model.ServerInfo;
import com.hp.snap.gr.model.jaxb.ActionType;
import com.hp.snap.gr.model.jaxb.GeneralActionType;
import com.hp.snap.gr.model.jaxb.ParameterType;
import com.hp.snap.gr.utils.Constants;
import com.hp.snap.gr.utils.GRMConfigManager;
import com.hp.snap.gr.utils.SSHTools;
import com.hp.snap.gr.utils.Utils;

public class CheckLogActionHandler extends AbstractActionHandler {

    private static Logger logger = LoggerFactory.getLogger(CheckLogActionHandler.class);
    private static final String ERROR = "error";
    private static final String WARN = "warn";
    
    @Override
    public void execute(ActionType action, Map<String, Object> actionPlanInputs, Map<String, Object> actionPlanOutputs)
            throws ActionException {
        GeneralActionType actionType = (GeneralActionType) action;
        List<ParameterType> parameterTypes = actionType.getParameter();
        Map<String, String> parameterMap = Utils.contructParamMap(parameterTypes);
        
        
        Integer errorThreshold = Integer.parseInt(parameterMap.get("ERROR_THRESGOLD"));
        if (logger.isDebugEnabled()) {
            logger.debug("the error threshold value is {}", errorThreshold);
        }
        
        @SuppressWarnings("unchecked")
        List<ServerInfo> serverLst = (List<ServerInfo>)actionPlanOutputs.get(Constants.SESSION_SERVER_RESPONSE_TEXT); 
        
        long totalErrorNum=0;
        long totalWarnNum=0;
        int logCheckResult=0;
        SSHTools ssh = null;
        int items=0;
        for(ServerInfo ssobj:serverLst){
            if (logger.isDebugEnabled()) {
                logger.debug("The session server info is {}", ssobj.toString());
            }
            String cmdresult;
            String remoteIp = ssobj.getHostIp();
            String sshUser = ssobj.getLogin();
            String sshKey = GRMConfigManager.decode("encrypt://"+ssobj.getSshKey());
            String servername=ssobj.getServerName();
            
            if(logger.isDebugEnabled()){
                logger.debug("The items is:{}", items++);
                logger.debug("remote ip:{}", remoteIp);
                logger.debug("sshUser is:{}", sshUser);
                logger.debug("encrypt ssh key is:{}",ssobj.getSshKey());
                logger.debug("SSH Key is:{}", sshKey);
                logger.debug("the server name is:{}", servername);
            }
            
            String logPath="/var/opt/"+ssobj.geteIUMInstance()+"/log/"+servername+".log";
            
            File keyFile = Utils.generateKeyFile(sshKey);
            String keyFilePath ="";
            try {
                 keyFilePath = keyFile.getCanonicalPath();   
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            if(logger.isDebugEnabled()){
                logger.debug("The key file path is {}",keyFilePath);
            }
            
            String shellScript ="/tmp/CheckLog.sh "+logPath;
            String scriptFilename = Utils.getConfigurationValue("USER_GR_ARTIFACT")+"/CheckLog.sh";
            if (logger.isDebugEnabled()) {
                logger.debug("the check log shell script is: {}", shellScript);
            }
             ssh = new SSHTools(sshUser, keyFilePath);
            try {       
//                cmdresult = ssh.executeRemoteShell(false, shellScript, remoteIp);
                cmdresult=ssh.executeRemoteScriptFile(new File(scriptFilename), shellScript, remoteIp);
                int status = ssh.getExitStatusOfCommandResult(cmdresult);
                String resultStr = ssh.getCommandOutput(cmdresult);
                if (logger.isDebugEnabled()) {
                    logger.debug("the log checking result is:{} of the server:{}", new Object[]{resultStr, remoteIp});
                }
                if (status != 0) {
                    logger.error("execute the checking log shell script failed!", remoteIp);
                    throw new ActionException("execute the checking " + remoteIp + " log shell script failed!");
                }
                Map<String, Integer> logStatus =  getErrorWarnLogNumber(resultStr);
                if(logger.isDebugEnabled()){
                    logger.debug("Error:{} Warn:{} in the session server {}", new Object[]{logStatus.get(ERROR), logStatus.get(WARN), servername});
                }
                totalErrorNum+=logStatus.get(ERROR);
                totalWarnNum+=logStatus.get(WARN);
            } catch (Exception e) {
                logger.error("can not connect the {} server to get log status",remoteIp);
                e.printStackTrace();
//                throw new ActionException(e.getMessage(), e.getCause());
            }    
        }
        if(ssh!=null) ssh.closeAll();
        
        if(logger.isDebugEnabled()){
            logger.debug("Total of error number is {}", totalErrorNum);
            logger.debug("Total of warn number is {}", totalWarnNum);
        }
        
        
        //check the log status  0:OK, 1:WARN, 2:ERROR
        if(totalErrorNum==0 && totalWarnNum==0)
            logCheckResult=0;
        else if(totalErrorNum>errorThreshold)
            logCheckResult=2;
        else if(totalErrorNum<=errorThreshold || totalWarnNum>0 )
            logCheckResult=1;
            
        
        Constants.CONSOLE.info(logCheckResult+"");
        

    }
    
    /**
     * 
     * Paese the log checking result
     *
     * @param resultStr { "error":12, "warn":110 }
     * @return 
     */
    private Map<String, Integer> getErrorWarnLogNumber(String resultStr) throws ActionException {
        Map<String, Integer> resultStatus=new HashMap<String, Integer>();
        
        try {
            JSONObject json = new JSONObject(resultStr);
            resultStatus.put(ERROR, Integer.parseInt(json.getString(ERROR)));
            resultStatus.put(WARN, Integer.parseInt(json.getString(WARN)));
        } catch (JSONException e) {
            logger.error(e.toString());
            ActionException e1 = new ActionException(e.getMessage(), e);
            throw e1;
        }
       
        return resultStatus;  
    }

}
